#include <cassert>
#include <cstdio>
#include <utility>
#include <pthread.h>
#include <sys/eventfd.h>
#include <algorithm>

#include "../../base/log/Logging.h"
#include "EventLoop.h"
#include "../tcp/Channel.h"
#include "Poller.h"
#include "TimerQueue.h"

__thread EventLoop *t_loopInThisThread = nullptr;

const int kPollTimeMs = 10000;
// const int kPollTimeMs = -1;
// 默认的一个poll超时时间

int createEventfd() {
    int evtfd = eventfd(0, EFD_NONBLOCK | EFD_CLOEXEC);
    // 创建空事件用于唤醒事件循环
    if (evtfd < 0) {
        LOG_SYSFATAL << "createEventfd 创建文件描述符失败";
    }
    return evtfd;
}

EventLoop::EventLoop() : looping_(false),
                         quit_(true),
                         eventHandling_(false),
                         callingPendingFunctors_(false),
                         threadId_(CurrentThread::getTid()),
                         poller_(Poller::newDefaultPoller(this)),
                         timerQueue_(new TimerQueue(this)),
                         wakeupFd_(createEventfd()),
                         wakeupChannel_(new Channel(this, wakeupFd_)),
                         currentActiveChannel_(nullptr) {
    LOG_DEBUG << "EventLoop创建" << this << ", 创建线程" << threadId_;
    if (t_loopInThisThread != nullptr) {
        LOG_FATAL << "已经存在EventLoop"
                  << t_loopInThisThread
                  << "在当前线程 : "
                  << threadId_ << "中";
    } else {
        t_loopInThisThread = this;
    }
    // 如果当前线程没有事件循环对象就赋值
    wakeupChannel_->setReadCallback(
            std::bind(&EventLoop::handleRead, this));
    // 用于唤醒的文件描述符也有对应的事件, 这个事件需要处理
    wakeupChannel_->enableReading();
}

EventLoop::~EventLoop() {
    assert(!looping_);
    LOG_DEBUG << "EventLoop : " << this << " 在线程" << threadId_ << "中被释放";
    wakeupChannel_->disableAll();
    wakeupChannel_->remove();
    ::close(wakeupFd_);
    t_loopInThisThread = nullptr;
}

void EventLoop::loop() {
    assert(!looping_);
    // 这里是先判断下事件循环是否在执行
    assertInLoopThread();
    // 检查是否在正确的线程中
    looping_ = true;
    // 表示现在事件循环正在工作
    quit_ = false;

    LOG_TRACE << "Eventloop : " << this << "启动looping";

    while (!quit_) {
        activeChannels_.clear();
        pollReturnTime_ = poller_->poll(kPollTimeMs, &activeChannels_);
        eventHandling_ = true;
        for (ChannelList::iterator it = activeChannels_.begin(); it != activeChannels_.end(); ++it) {
            currentActiveChannel_ = *it;
            (*it)->handleEvent(pollReturnTime_);
            // 调用对应的事件处理函数
        }
        currentActiveChannel_ = nullptr;
        eventHandling_ = false;
        doPendingFunctors();
        // 执行保存在pendingFunctors中的事件
    }

    LOG_TRACE << "EventLoop : " << this << "停止looping";
    looping_ = false;
    // 结束循环
}

void EventLoop::quit() {
    quit_ = true;
    // 结束事件循环的条件
    if (!isInLoopThread()) {
        wakeup();
    }
}

void EventLoop::runInLoop(const EventLoop::Functor &cb) {
    if (isInLoopThread()) {
        cb();
        // 如果是在当前线程(IO线程)就调用对应事件的回调函数
    } else {
        queueInLoop(cb);
        // 如果不是在IO线程就转移到IO线程调用
    }

}

void EventLoop::queueInLoop(const EventLoop::Functor &cb) {
    {
        MutexLockGuard lock(mutex_);
        pendingFunctors_.push_back(cb);
    }
    if (!isInLoopThread() || callingPendingFunctors_) {
        wakeup();
        // 只有在IO线程的事件回调中才不用调用wakeup
    }
}

TimerId EventLoop::runAt(Timestamp time, EventLoop::TimerCallback cb) {
    return timerQueue_->addTimer(std::move(cb), time, 0.0);
}

TimerId EventLoop::runAfter(double delay, EventLoop::TimerCallback cb) {
    Timestamp time(addTime(Timestamp::now(), delay));
    return runAt(time, std::move(cb));
}

TimerId EventLoop::runEvery(double interval, EventLoop::TimerCallback cb) {
    Timestamp time(addTime(Timestamp::now(), interval));
    return timerQueue_->addTimer(std::move(cb), time, interval);
}

void EventLoop::abortNotInLoopThread() {
    LOG_FATAL << "EventLoop::abortNotInLoopThread - EventLoop " << this
              << " 创建线程id为 = " << threadId_
              << ", 当前使用的线程id = " << CurrentThread::getTid();
}

void EventLoop::cancel(TimerId timerId) {
    return timerQueue_->cancel(timerId);
}


void EventLoop::wakeup() {
    uint64_t one = 1;
    ssize_t n = write(wakeupFd_, &one, sizeof one);
    // 通过让Poller监听对应的wakeupFd来唤醒事件
    if (n != sizeof one) {
        LOG_ERROR << "EventLoop::wakeup() writes " << n << " bytes instead of 8";
    }
}

void EventLoop::updateChannel(Channel *channel) {
    assert(channel->ownerLoop() == this);
    assertInLoopThread();
    poller_->updateChannel(channel);
}

void EventLoop::removeChannel(Channel *channel) {
    assert(channel->ownerLoop() == this);
    assertInLoopThread();
    if (eventHandling_) {
        assert(currentActiveChannel_ == channel ||
               std::find(activeChannels_.begin(), activeChannels_.end(), channel) == activeChannels_.end());
    }
    poller_->removeChannel(channel);
    // 移除Channel
}

bool EventLoop::hasChannel(Channel *channel) {
    assert(channel->ownerLoop() == this);
    assertInLoopThread();
    return poller_->hasChannel(channel);
}

EventLoop *EventLoop::getEventLoopOfCurrentThread() {
    return t_loopInThisThread;
    // 获取并返回当前线程中的事件循环
}

void EventLoop::handleRead() {
    uint64_t one = 1;
    ssize_t n = ::read(wakeupFd_, &one, sizeof one);
    if (n != sizeof one) {
        LOG_ERROR << "EventLoop::handleRead() reads " << n << " bytes instead of 8";
    }
}

void EventLoop::doPendingFunctors() {
    std::vector<Functor> functors;
    callingPendingFunctors_ = true;
    // 表示现在正在执行事件回调
    {
        MutexLockGuard lock(mutex_);
        functors.swap(pendingFunctors_);
    }

    for (int i = 0; i < functors.size(); ++i) {
        functors[i]();
    }
    callingPendingFunctors_ = false;
}

